/**
 * Project Name:Micro-Services-RPC-Message
 * File Name   :PropertyChangeListener.java
 * Package Name:test.event
 * Date:2015-9-9上午10:02:40
 * Copyright (c) 2015, http://my.oschina.net/httpssl All Rights Reserved.
 *
 */

package test.event;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyVetoException;
import java.beans.VetoableChangeListener;
import java.io.PrintStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Date;

import org.apache.commons.lang3.event.EventListenerSupport;
import org.apache.commons.lang3.reflect.FieldUtils;

import com.micro.services.common.utils.ReflectUtils;

/**
 * ClassName:PropertyChangeListener <br/>
 * Function :TODO ADD 测试 学习 对象属性监听. <br/>
 * Reason :TODO PropertyChangeEvent,VetoableChangeListener. <br/>
 * Date :2015-9-9 上午10:02:40 <br/>
 * 
 * @author :http://my.oschina.net/httpssl
 * @since :JDK 1.7
 * @see
 */
@SuppressWarnings("all")
public class PropertyChangeListener
{
	public static class EventWorker
	{

		public static final String	PROP_WORKSTATE	= "workState";

		private final int			id;
		private final String		name;
		private volatile String		workState;

		public EventWorker(int id, String name)
		{
			super();
			this.id = id;
			this.name = name;
		}

		public EventWorker(int id, String name, String workState)
		{
			super();
			this.id = id;
			this.name = name;
			this.workState = workState;
		}

		public String getWorkState() {
			return workState;
		}

		public void setWorkState(String workState) {
			this.workState = workState;
		}

	}

	public static void main(String[] args) throws PropertyVetoException {
		final EventListenerSupport<VetoableChangeListener> listenerSupport = EventListenerSupport
				.create(VetoableChangeListener.class);
		// listenerSupport.addListener(null);//不能添加一个null对象
		// listenerSupport.removeListener(null);//不能移除一个null

		VetoableChangeListener newVetoableChangeListener = new VetoableChangeListener()
		{
			/*
			 * 
			 * TODO VetoableChangeListener 监听对象 触发属性 change时触发  * @see
			 * java.beans
			 * .VetoableChangeListener#vetoableChange(java.beans.PropertyChangeEvent
			 * )
			 */
			@Override
			public void vetoableChange(PropertyChangeEvent evt) throws PropertyVetoException {
				PrintStream stream = System.err;
				if (!ReflectUtils.isPrimitive(evt.getSource().getClass())) {
					try {
						Field field = evt.getSource().getClass()
								.getDeclaredField(evt.getPropertyName());
						//
						if (!field.isAccessible()) {
							field.setAccessible(true);
						}
						FieldUtils.writeField(field, evt.getSource(), evt.getNewValue());
					} catch (NoSuchFieldException e) {
						stream.append(e.getMessage());
					} catch (SecurityException e) {
						stream.append(e.getMessage());
					} catch (IllegalAccessException e) {
						stream.append(e.getMessage());
					} finally {
						stream.println();
					}
					System.out.println(evt.getPropertyName() + " " + evt.getOldValue() + "  -> "
							+ evt.getNewValue());
				}
			}
		};

		EventWorker developer = new EventWorker(1, "开发A", "正在开发");

		listenerSupport.addListener(newVetoableChangeListener);
		// 一定要写在addListener 后
		listenerSupport.fire().vetoableChange(
				new PropertyChangeEvent(developer, EventWorker.PROP_WORKSTATE, developer
						.getWorkState(), "完成了"));

		System.out.println("在方法外 查看:::" + developer.getWorkState());

		final EventListenerSupport<VetoableChangeListener> eventListenerSupport2 = new EventListenerSupport<VetoableChangeListener>(
				VetoableChangeListener.class)
		{

			private static final long	serialVersionUID	= 1L;

			protected java.lang.reflect.InvocationHandler createInvocationHandler() {
				return new ProxyInvocationHandler()
				{
					/*
					 * 
					 * TODO 简单描述该方法的实现功能（可选）.  * @see
					 * org.apache.commons.lang3.event
					 * .EventListenerSupport.ProxyInvocationHandler
					 * #invoke(java.lang.Object, java.lang.reflect.Method,
					 * java.lang.Object[])
					 */
					@Override
					public Object invoke(Object proxy, Method method, Object[] args)
							throws Throwable {
						return super.invoke(proxy, method, args);
					}
				};
			}

		};

		final VetoableChangeListener listener = new VetoableChangeListener()
		{
			@Override
			public void vetoableChange(PropertyChangeEvent evt) throws PropertyVetoException {
				System.out.println(evt.getPropertyName() + " " + evt.getOldValue() + "  -> "
						+ evt.getNewValue());
			}
		};
		eventListenerSupport2.addListener(listener);
		final Date source = new Date();

		final PropertyChangeEvent ignore = new PropertyChangeEvent(source, "Hour", 5, 6);
		final PropertyChangeEvent respond = new PropertyChangeEvent(source, "Day", 6, 7);
		listener.vetoableChange(respond);
		eventListenerSupport2.fire().vetoableChange(ignore);
		eventListenerSupport2.fire().vetoableChange(respond);

	}

	public static class PropertyChangeSource
	{
		final EventListenerSupport<VetoableChangeListener> listeners = EventListenerSupport.create(VetoableChangeListener.class);
		private String												property;

		public void setProperty(final String property) throws PropertyVetoException {
			final String oldValue = this.property;
			this.property = property;
			listeners.fire().vetoableChange(new PropertyChangeEvent(this, "property", oldValue, property));
		}

		protected void addVetoableChangeListener(final VetoableChangeListener listener) {
			listeners.addListener(listener);
		}

		public void removeVetoableChangeListener(final VetoableChangeListener listener) {
			listeners.removeListener(listener);
		}
	}

}
